//Copyright 2010 Balazs Keri, Imre Keri
//
//This file is part of FireworksCreator.
//
//FireworksCreator is free software: you can redistribute it and/or modify
//it under the terms of the GNU General Public License as published by
//the Free Software Foundation, either version 3 of the License, or
//(at your option) any later version.
//
//FireworksCreator is distributed in the hope that it will be useful,
//but WITHOUT ANY WARRANTY; without even the implied warranty of
//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//GNU General Public License for more details.
//
//You should have received a copy of the GNU General Public License
//along with FireworksCreator.  If not, see <http://www.gnu.org/licenses/>.
//
#ifndef _DOCUMENT_H
#define _DOCUMENT_H
#include <QObject>
#include <QString>
#include <common/id.h>
#include <common/iddictionary.h>
#include <common/idgenerator.h>
#include <common/identified_fwd.h>
#include <model/root_fwd.h>
//
class PrimitiveGroup;
class Primitive;
class Document:public QObject
{
   Q_OBJECT
   Q_DISABLE_COPY(Document)
   friend class PrimitiveGroup;
   friend class Primitive;
   friend class SimpleTextView; //temporary
//data
private:
   struct HistoryTreeItem
   {
      QScopedPointer<PrimitiveGroup> op;
      HistoryTreeItem *parent;
      QList<QSharedPointer<HistoryTreeItem> > children;
      HistoryTreeItem(PrimitiveGroup *p_op=0,HistoryTreeItem *p_parent=0);
   };
//construction
public:
   Document(QObject *parent=0);
   ~Document();
//get functions
public:
   model::Root *get_root() const;
   double get_firework_length() const;
   QString get_file_name() const;
   const IdDictionary &get_id_map() const;
//services
public:
   Id generate_id();
   void map_object(Identified *p_object);
   void unmap_object(Identified *p_object);
   Identified *lookup_object(Id p_id);
   const Identified *lookup_object(Id p_id) const;
   void set_modified(bool m);
   bool get_modified() const;
   void initialize_new();
//file i/o
public:
   bool load(const QString &p_file_name);
   bool save(const QString &p_file_name);
//operation execution
public:
   bool undo();
   bool redo(int i);
   QString get_undo_op_description() const;
   QStringList get_redo_op_descriptions() const;
//implementation
private:
   void emit_pre_primitive(const Primitive &prim);
   void emit_post_primitive(const Primitive &prim);
   void emit_fail_primitive(const Primitive &prim);
   void emit_post_primitive_group(const PrimitiveGroup &p_prim_grp);
   bool add_to_history(PrimitiveGroup *op); //only the PrimitiveGroup may call this
   //bool register_pending_op(PrimitiveGroup *p_op);
   //bool preview_pending_op();
   //bool cancel_pending_op();
   //bool apply_pending_op();
   //bool undo_current_op();
   //bool set_current_op(HistoryTreeItem *p_op);
//signals
signals:
   void pre_primitive(const Primitive &prim);
   void post_primitive(const Primitive &prim);
   void fail_primitive(const Primitive &prim);
   void post_primitive_pre(Primitive *prim);
   void post_primitive_post(Primitive *prim);
   void post_primitive_group(const PrimitiveGroup &p_prim_grp);
   void history_changed();
   void modified_changed(bool modified);
//internal
private:
   void delete_contents();
   void delete_op_tree_children(HistoryTreeItem *subtree);
   /*void find_op_path(HistoryTreeItem *current,
                     HistoryTreeItem *from,
                     HistoryTreeItem *to,
                     QList<HistoryTreeItem*> &path,
                     unsigned int &state,
                     int &junction);*/
   void store_history(const HistoryTreeItem &p_tree, QDataStream &p_stream);
   void restore_history(HistoryTreeItem &p_tree, RestoreStream &p_stream);
//data
private:
   QScopedPointer<model::Root> fw_root;
   IdGenerator id_gen;
   IdDictionary id_map;
   HistoryTreeItem history_root;
   HistoryTreeItem *current_operation;
   //PrimitiveGroup *pending_operation;
   bool modified;
   static const qint32 data_version_1_qt_4_6;
   static const quint32 data_check_value;
};

#endif
